home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / rbbs_pc / aed243a.zip / ANSIED-3.BAS < prev    next >
BASIC Source File  |  1990-06-10  |  44KB  |  1,337 lines

  1. '*
  2. '*  ANSIED v2.43a
  3. '*---------------------------------------------------------------------------
  4. '*  Full Screen Text Editor for RBBS-PC
  5. '*  QuickBASIC v3.0 Version
  6. '*  06-10-90
  7. '*
  8. '*  v2.1xx ... made it work with RBBS v17
  9. '*  v2.2 ..... fixed some inconsistincies in the code as to # of lines in msg.
  10. '*             Some of the code thought 99 was length, some thought 100.
  11. '*  v2.3 ..... let it work with quoted reply.  No more REDIM of ZOutTxt$
  12. '*  v2.4 ..... removed tabs, margins code to be smaller
  13. '*  v2.41..... fixed bug with loss of bold attribute occasionally
  14. '*  v2.42..... made it work as a v17.3 subroutine.  Added block delete.
  15. '*  v2.43..... Added to: and from:.  Made cursor keys work locally.
  16. '*  v2.43a.... Stupid little bugs fixed
  17. '*
  18. '*  Returns:
  19. '*  ZSubParm  =  1 - Save Message
  20. '*            =  2 - Abort Message
  21. '*            = -1 - Dropped Carrier
  22. '*            = -2 - Sleep Disconnect
  23. '*
  24. '*
  25.  
  26. ' $INCLUDE: 'RBBS-VAR.MOD'
  27.  
  28. 100   CONST ColorRset = 0
  29.       CONST RedFore = 31
  30.       CONST GreenFore = 32
  31.       CONST YellowFore = 33
  32.       CONST BlueFore = 34
  33.       CONST MagentaFore = 35
  34.       CONST CyanFore = 36
  35.       CONST WhiteFore = 37
  36.       CONST BlueBack = 44
  37.  
  38. 110   CONST ESCKey = 27
  39.       CONST BackspKey = 8
  40.       CONST OtherBackspKey = 127
  41.       CONST CarrRet = 13
  42.       CONST ReformTextKey = 2    ' Ctrl-B
  43.       CONST EndSessionKey = 11   ' Ctrl-K
  44.       CONST HelpKey = 14         ' Ctrl-N
  45.       CONST ReflowTextKey = 15   ' Ctrl-O
  46.       CONST RepaintKey = 16      ' Ctrl-P
  47.       CONST ToggleINSKey = 22    ' Ctrl-V
  48.       CONST LineUpKey = 5        ' Ctrl-E
  49.       CONST LineDownKey = 24     ' Ctrl-X
  50.       CONST ColLeftKey = 19      ' Ctrl-S
  51.       CONST ColRightKey = 4      ' Ctrl-D
  52.       CONST WordLeftKey = 1      ' Ctrl-A
  53.       CONST WordRightKey = 6     ' Ctrl-F
  54.       CONST PageUpKey = 18       ' Ctrl-R
  55.       CONST PageDownKey = 3      ' Ctrl-C
  56.       CONST HomeKey = 23         ' Ctrl-W
  57.       CONST EndKey = 26          ' Ctrl-Z
  58.       CONST LineDeleteKey = 25   ' Ctrl-Y
  59.       CONST CharDeleteKey = 7    ' Ctrl-G
  60.  
  61.       CONST BlankLine$ = ""
  62. 119   CONST Version$ = "v2.43a"
  63.  
  64.       DEFINT A-Z
  65.  
  66. 120   COMMON SHARED /Ansied/ CurrentRow, CurrentCol, TopLine
  67.       COMMON SHARED /Ansied/ OldColour, IsBold, InsertMode
  68.       COMMON SHARED /Ansied/ SoftSpace$, InsOvwPosition
  69.       COMMON SHARED /Ansied/ BlockDelActive, MsgLockLines
  70.       COMMON SHARED /Ansied/ BlockLine1, BlockLine2
  71.       COMMON SHARED /Ansied/ MsgTo$, MsgSubj$
  72.  
  73. '*  AnsiEd
  74. '*----------------------------------------------------------------------------
  75. '*  Main full-screen editor routine
  76. '*
  77. '*
  78.       SUB Ansied (T$, S$, L%) STATIC
  79.  
  80.       '*
  81.       '* ZworkAra$() holds what's currently on the user's screen.
  82.       '* 24 Lines: ZWorkAra$(1) = Menu, Bottom Line = "Line 25"
  83.       '*
  84. 500   REDIM ZWorkAra$(24)
  85.       '*
  86.       '* TopLine is the index into the ZOutTxt$() array that
  87.       '* corresponds to the top of the displayed image, i.e.
  88.       '* what's on line 2 of the user's screen.
  89.       '*
  90.       '*   1,12,23,34,45,56,78
  91.       '*
  92.       TopLine = 1
  93.       SoftSpace$ = CHR$(250)
  94.       InsertMode = ZTrue
  95.       ZLineFeed$ = CHR$(10)
  96.       OldColour = 0
  97.       Bold = ZFalse
  98.       IsBold = 99
  99.       BlockDelActive = ZFalse
  100.       CurrentCol = 0
  101.       CurrentRow = 0
  102.  
  103.       MsgLockLines = L
  104.  
  105.       MsgTo$ = T$
  106.       CALL NameCaps(MsgTo$)
  107.  
  108.       MsgSubj$ = S$
  109.       ZOutTxt$ = ""
  110.       IF LEFT$(MsgSubj$, 3) = "(R)" THEN
  111.          ZOutTxt$ = "(R)"
  112.          MsgSubj$ = MID$(MsgSubj$, 4)
  113.       END IF
  114.       CALL NameCaps(MsgSubj$)
  115.       MsgSubj$ = ZOutTxt$ + MsgSubj$
  116.  
  117.       '*
  118.       '* Initialize the screen array as all blanks
  119.       '*
  120. 510   FOR I = 3 TO 24
  121.          ZWorkAra$(I) = BlankLine$
  122.       NEXT I
  123.  
  124.       '*
  125.       '* Initialize the screen
  126.       '*
  127.       CALL ClearScreen
  128.       CALL UpdateStatusLine(1)
  129.       CALL MoveCursor(3, 1)
  130.       '*
  131.       '* Remove ANSI sequences from the quoted lines
  132.       '*
  133.       IF ZLinesInMsg > 88 THEN
  134.          ZLinesInMsg = 88
  135.       END IF
  136.       IF ZMaxMsgLines > 98 THEN
  137.          ZMaxMsgLines = 98
  138.       END IF
  139.       IF ZLinesInMsg > ZMaxMsgLines THEN
  140.          ZLinesInMsg = ZMaxMsgLines
  141.       END IF
  142.       FOR I = ZLinesInMsg + 1 TO 99
  143.          ZOutTxt$(I) = BlankLine$
  144.       NEXT
  145.       IF ZLinesInMsg <> 0 THEN
  146.          FOR I = 1 TO ZLinesInMsg
  147.             CALL UnString(ZOutTxt$(I), "")
  148.          NEXT
  149.          I! = ZLinesInMsg / 11
  150.          J = FIX(I!)
  151.          IF J = I! THEN
  152.            J = J - 1
  153.          END IF
  154.          TopLine = J * 11 + 1
  155.          J = ZLinesInMsg - TopLine
  156.          CALL MoveCursor(J + 5, 1)
  157.       END IF
  158.       CALL UpdateScreen
  159.  
  160.       '*
  161.       '* Run the Editor
  162.       '*
  163. 520   WHILE ZTrue
  164.  
  165.          CALL Carrier: GOSUB 740
  166.  
  167.          CALL Getch(B$): GOSUB 740
  168.          KeyPressed = ASC(B$)
  169.  
  170.          Index = CurrentRow + TopLine - 3
  171.  
  172.          IF BlockDelActive OR Index <= MsgLockLines OR Index > ZMaxMsgLines THEN
  173. 530         SELECT CASE KeyPressed
  174.                CASE CarrRet
  175.                   IF BlockDelActive THEN
  176.                      BlockDelActive = ZFalse
  177.                      BlockLine2 = Index
  178.                      IF Index < BlockLine1 THEN
  179.                         BlockLine2 = BlockLine1
  180.                         BlockLine1 = Index
  181.                      END IF
  182.                      IF BlockLine1 <= MsgLockLines THEN
  183.                         BlockLine1 = MsgLockLines + 1
  184.                      END IF
  185.                      IF BlockLine2 > ZMaxMsgLines THEN
  186.                         BlockLine2 = ZMaxMsgLines
  187.                      END IF
  188.                      K = 0
  189.                      FOR I = BlockLine2 + 1 TO 99
  190.                         ZOutTxt$(BlockLine1 + K) = ZOutTxt$(I)
  191.                         K = K + 1
  192.                      NEXT I
  193.                      WHILE BlockLine1 + K <= 99
  194.                         ZOutTxt$(BlockLine1 + K) = BlankLine$
  195.                         K = K + 1
  196.                      WEND
  197.                      CALL UpdateScreen
  198.                      CALL UpdateStatusLine(2)
  199.                      CALL MoveCursor(RowSave, ColSave)
  200.                   END IF
  201.                   KeyPressed = 255
  202.  
  203. 540            CASE ESCKey
  204.                   IF BlockDelActive THEN
  205.                      BlockDelActive = ZFalse
  206.                      CALL SaveCursor(RowSave, ColSave)
  207.                      CALL UpdateStatusLine(2)
  208.                      CALL MoveCursor(RowSave, ColSave)
  209.                      KeyPressed = 255
  210.                   END IF
  211.  
  212.                CASE LineUpKey, LineDownKey, PageDownKey, PageUpKey
  213.                   '*
  214.                   '* Up and Down get passed on
  215.                   '*
  216.                CASE ELSE
  217.                   '*
  218.                   '* Ignore the key
  219.                   '*
  220.                   KeyPressed = 255
  221.  
  222.             END SELECT
  223.          END IF
  224.  
  225.          '*
  226.          '* Look for an ANSI escape sequence after an ESC
  227.          '*
  228. 550      IF KeyPressed = ESCKey THEN
  229.             CALL Getch(B$): GOSUB 740
  230.             IF B$ = "[" THEN                    ' ANSI sequence
  231.                CALL Getch(B$): GOSUB 740
  232.                IF B$ = "C" THEN
  233.                   KeyPressed = ColRightKey
  234.                ELSEIF B$ = "D" THEN
  235.                   KeyPressed = ColLeftKey
  236.                ELSEIF B$ = "A" THEN
  237.                   KeyPressed = LineUpKey
  238.                ELSEIF B$ = "B" THEN
  239.                   KeyPressed = LineDownKey
  240.                END IF
  241.             END IF
  242.          END IF
  243.  
  244. 560      SELECT CASE KeyPressed
  245.             CASE ESCKey
  246.                '*
  247.                '* User wants to see main menu
  248.                '*
  249.                CALL SaveCursor(RowSave, ColSave)
  250.                CALL DisplayMainMenu
  251.                CALL MoveCursor(RowSave, ColSave)
  252.                KeyPressed = 255: B$ = ""
  253.                WHILE KeyPressed <> ESCKey
  254.                   CALL Getch(B$): GOSUB 740
  255.                   CALL AllCaps(B$)
  256.                   KeyPressed = ASC(B$)
  257.                   IF KeyPressed = CarrRet THEN
  258.                      B$ = "H"
  259.                   END IF
  260.                   I = INSTR("HJREIPB" + CHR$(ESCKey), B$)
  261.                   IF I = 7 THEN
  262.                      BlockDelActive = ZTrue
  263.                      BlockLine1 = RowSave + TopLine - 3
  264.                      CALL ClearMainMenu
  265.                      CALL QuickTput(ZEmphasizeOff$, 0)
  266.                      CALL PutScreen("Block Delete: Move cursor to last line to delete and press ENTER   ESC Quits", 99, ZFalse)
  267.                      CALL MoveCursor(RowSave, ColSave)
  268.                      BlockLine2 = 0
  269.                      KeyPressed = ESCKey
  270.                   ELSEIF I <> 0 THEN
  271.                      CALL ExecuteMainMenuCommand(B$): GOSUB 740
  272.                      KeyPressed = ESCKey
  273.                   END IF
  274.                WEND
  275.                CALL MoveCursor(RowSave, ColSave)
  276.  
  277. 570         CASE LineUpKey
  278.                '*
  279.                '* Move the current cursor position up one line
  280.                '*
  281.                IF CurrentRow > 3 THEN
  282.                   CALL MoveCursor(CurrentRow - 1, CurrentCol)
  283.                ELSE
  284.                   IF TopLine <> 1 THEN
  285.                      TopLine = TopLine - 11
  286.                      CALL MoveCursor(CurrentRow + 10, CurrentCol)
  287.                      CALL UpdateScreen
  288.                   END IF
  289.                END IF
  290.  
  291. 580         CASE LineDownKey
  292.                '*
  293.                '* Move the current cursor position down one line
  294.                '*
  295.                IF CurrentRow < 24 THEN
  296.                   CALL MoveCursor(CurrentRow + 1, CurrentCol)
  297.                ELSE
  298.                   IF NOT TopLine = 78 THEN
  299.                      TopLine = TopLine + 11
  300.                      CALL MoveCursor(CurrentRow - 10, CurrentCol)
  301.                      CALL UpdateScreen
  302.                   END IF
  303.                END IF
  304.  
  305. 590         CASE ColLeftKey
  306.                '*
  307.                '* Move the current cursor left one column
  308.                '*
  309.                IF CurrentCol > 1 THEN
  310.                   CALL MoveCursor(CurrentRow, CurrentCol - 1)
  311.                END IF
  312.  
  313. 600         CASE ColRightKey
  314.                '*
  315.                '* Move the current cursor right one column
  316.                '*
  317.                IF CurrentCol < 79 THEN
  318.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  319.                END IF
  320.  
  321. 610         CASE WordRightKey
  322.                '*
  323.                '* Move the current cursor right one word
  324.                '*
  325.                FOR I = CurrentCol TO LEN(ZOutTxt$(Index)) - 1
  326.                   YY$ = MID$(ZOutTxt$(Index), I, 1)
  327.                   ZZ$ = MID$(ZOutTxt$(Index), I + 1, 1)
  328.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  329.                      NewCol = I + 1
  330.                      IF NewCol > 79 THEN
  331.                         NewCol = 79
  332.                      END IF
  333.                      CALL MoveCursor(CurrentRow, NewCol)
  334.                      EXIT FOR
  335.                   END IF
  336.                NEXT I
  337.  
  338. 620         CASE WordLeftKey
  339.                '*
  340.                '* Move the current cursor left one word
  341.                '*
  342.                Found = ZFalse
  343.                FOR I = CurrentCol - 1 TO 2 STEP -1
  344.                   ZZ$ = MID$(ZOutTxt$(Index), I, 1)
  345.                   YY$ = MID$(ZOutTxt$(Index), I - 1, 1)
  346.                   IF (YY$ = " " OR YY$ = SoftSpace$) AND ZZ$ <> " " AND ZZ$ <> SoftSpace$ THEN
  347.                      NewCol = I
  348.                      CALL MoveCursor(CurrentRow, NewCol)
  349.                      Found = ZTrue
  350.                      EXIT FOR
  351.                   END IF
  352.                NEXT I
  353.                IF NOT Found THEN
  354.                   CALL MoveCursor(CurrentRow, 1)
  355.                END IF
  356.  
  357. 630         CASE HomeKey
  358.                '*
  359.                '* Move cursor to the start of the line
  360.                '*
  361.                CALL MoveCursor(CurrentRow, 1)
  362.  
  363. 640         CASE EndKey
  364.                '*
  365.                '* Move cursor to the end of the line
  366.                '*
  367.                IF ZOutTxt$(Index) = STRING$(79, 250) THEN
  368.                   NewCol = 1
  369.                ELSE
  370.                   NewCol = 0
  371.                   FOR I = LEN(ZOutTxt$(Index)) TO 1 STEP -1
  372.                      IF MID$(ZOutTxt$(Index), I, 1) <> SoftSpace$ THEN
  373.                         NewCol = I + 1
  374.                         EXIT FOR
  375.                      END IF
  376.                   NEXT I
  377.                   IF NewCol > 79 THEN
  378.                      NewCol = 79
  379.                   ELSEIF NewCol < 1 THEN
  380.                      NewCol = 1
  381.                   END IF
  382.                END IF
  383.                CALL MoveCursor(CurrentRow, NewCol)
  384.  
  385. 650         CASE PageDownKey
  386.                '*
  387.                '* Move the display one page down
  388.                '*
  389.                TopLine = TopLine + 22
  390.                IF TopLine > 78 THEN
  391.                   TopLine = 78
  392.                END IF
  393.                CALL UpdateScreen
  394.  
  395. 660         CASE PageUpKey
  396.                '*
  397.                '* Move the display one page up
  398.                '*
  399.                TopLine = TopLine - 22
  400.                IF TopLine < 1 THEN
  401.                   TopLine = 1
  402.                END IF
  403.                CALL UpdateScreen
  404.  
  405. 670         CASE LineDeleteKey
  406.                '*
  407.                '* Delete the current line in the file
  408.                '*
  409.                CALL SaveCursor(RowSave, ColSave)
  410.                CALL DeleteCurrentLine(Index)
  411.                CALL MoveCursor(RowSave, ColSave)
  412.  
  413. 680         CASE CharDeleteKey
  414.                '*
  415.                '* Delete the current character
  416.                '*
  417.                IF CurrentCol <= LEN(ZOutTxt$(Index)) THEN
  418.                   CALL MoveCursor(CurrentRow, CurrentCol + 1)
  419.                   CALL BackspChar
  420.                END IF
  421.  
  422. 690         CASE BackspKey, OtherBackspKey
  423.                '*
  424.                '* Back up one character and destroy it
  425.                '*
  426.                CALL BackspChar
  427.  
  428. 700         CASE CarrRet
  429.                '*
  430.                '* Move to the next line, left column
  431.                '*
  432.                IF NOT Index >= ZMaxMsgLines THEN
  433.                   CALL CarrRetKey
  434.                END IF
  435.  
  436. 710         CASE HelpKey, ReformTextKey, ReflowTextKey, EndSessionKey, ToggleINSKey, RepaintKey
  437.                '*
  438.                '* Execute a main menu command
  439.                '*
  440.                '*          1234567890123456789012
  441.                YY$ = MID$(" J        E  HRP     I", KeyPressed, 1)
  442.                CALL SaveCursor(RowSave, ColSave)
  443.                CALL ExecuteMainMenuCommand(YY$): GOSUB 740
  444.                CALL MoveCursor(RowSave, ColSave)
  445.  
  446.             CASE IS > 127, IS < 32
  447.                '*
  448.                '* Ignore characters above 127 or below 32
  449.                '*
  450. 720         CASE ELSE
  451.                '*
  452.                '* Input was a normal character
  453.                '*
  454.                CALL NormalChar(B$)
  455.  
  456.          END SELECT
  457.       WEND
  458.  
  459. 730   REDIM ZWorkAra$(13)
  460.       EXIT SUB
  461.  
  462.       '*
  463.       '* Test ZSubParm and Exit ANSIED if the carrier dropped
  464.       '*
  465. 740   IF ZSubParm <> 0 THEN
  466.          GOTO 730
  467.       END IF
  468.       RETURN
  469.  
  470.       END SUB         ' Sub AnsiEd
  471.  
  472. '*  BackspChar()
  473. '*----------------------------------------------------------------------------
  474. '*  This routine handles the user entering the backspace key
  475. '*
  476. '*
  477.       SUB BackspChar STATIC
  478. 1200  CALL SaveCursor(RowSave, ColSave)
  479.       Index = TopLine + CurrentRow - 3
  480.       IF Index = MsgLockLines + 1 AND CurrentCol = 1 THEN
  481.          EXIT SUB
  482.       END IF
  483.       AtEndOfLine = CurrentCol > LEN(ZOutTxt$(Index))
  484. 1210  IF CurrentCol > 1 THEN
  485.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 2) + MID$(ZOutTxt$(Index), CurrentCol)
  486.          CALL EraseToEOL(CurrentRow, CurrentCol - 1)
  487.          IF NOT AtEndOfLine THEN
  488.             YY$ = MID$(ZOutTxt$(Index), ColSave - 1)
  489.             CALL MoveCursor(RowSave, ColSave - 1)
  490.             CALL PutScreen(YY$, YellowFore, ZTrue)
  491.          END IF
  492.          CALL MoveCursor(RowSave, ColSave - 1)
  493.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  494.       ELSEIF LEN(ZOutTxt$(Index - 1)) >= ZRightMargin THEN
  495.          '*
  496.          '* Do nothing
  497.          '*
  498. 1220  ELSE
  499.          NewCol = LEN(ZOutTxt$(Index - 1)) + 1
  500.          YY$ = ZOutTxt$(Index)
  501.          CALL UnString(YY$, SoftSpace$)
  502.          ZOutTxt$(Index - 1) = ZOutTxt$(Index - 1) + YY$
  503.          IF LEN(ZOutTxt$(Index - 1)) < ZRightMargin THEN
  504.             CALL DeleteCurrentLine(Index)
  505. 1230     ELSE
  506.             CALL FindWrap(LEFT$(ZOutTxt$(Index - 1), ZRightMargin + 1), I)
  507.             IF I = 0 OR I = 1 THEN
  508.                I = ZRightMargin
  509.             END IF
  510.             ZOutTxt$(Index) = MID$(ZOutTxt$(Index - 1), I + 1)
  511.             ZOutTxt$(Index - 1) = LEFT$(ZOutTxt$(Index - 1), I)
  512.          END IF
  513.          IF RowSave > 3 THEN
  514.             CALL MoveCursor(RowSave - 1, NewCol)
  515.             CALL UpdateScreen
  516.          ELSE
  517.             CALL MoveCursor(RowSave, NewCol)
  518.             CALL Ungetch(LineUpKey)
  519.          END IF
  520.       END IF
  521.       END SUB
  522.  
  523. '*  CarrRetKey()
  524. '*----------------------------------------------------------------------------
  525. '*  This routine handles carriage returns entered in the file
  526. '*
  527. '*
  528.       SUB CarrRetKey STATIC
  529. 1300  Index = CurrentRow + TopLine - 3
  530.       IF Index >= 99 THEN
  531.          EXIT SUB
  532.       END IF
  533.       IF InsertMode THEN         ' Insert a new line
  534.          FOR I = 98 TO Index + 1 STEP -1
  535.             ZOutTxt$(I + 1) = ZOutTxt$(I)
  536.          NEXT I
  537.          IF LEN(ZOutTxt$(Index)) >= CurrentCol THEN
  538.             ZOutTxt$(Index + 1) = MID$(ZOutTxt$(Index), CurrentCol)
  539.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1)
  540.          ELSE
  541.             ZOutTxt$(Index + 1) = BlankLine$
  542.          END IF
  543.          CALL UpdateScreen
  544.       END IF
  545.       IF CurrentRow < 24 THEN
  546.          CALL MoveCursor(CurrentRow + 1, 1)
  547.       ELSE
  548.          CALL MoveCursor(CurrentRow, 1)
  549.          CALL Ungetch(LineDownKey)
  550.       END IF
  551.       END SUB
  552.  
  553. '*  ClearMainMenu()
  554. '*----------------------------------------------------------------------------
  555. '*  This routine clears the main menu from the top line.  The cursor is
  556. '*  moved to row 1, column 1.
  557. '*
  558.       SUB ClearMainMenu STATIC
  559. 1400  CALL EraseToEOL(1, 1)
  560.       CALL MoveCursor(1, 1)
  561.       END SUB
  562.  
  563. '*  ClearScreen()
  564. '*----------------------------------------------------------------------------
  565. '*  This routine clears the screen and moves the cursor to row 2, col 1
  566. '*
  567. '*
  568.       SUB ClearScreen STATIC
  569. 1500  FOR I = 1 TO 23
  570.          ZWorkAra$(I) = BlankLine$
  571.       NEXT I
  572.       CALL QuickTput("H", 0)      ' clear screen, column 1, row 3
  573.       ZSubParm = 2
  574.       CALL Line25
  575.       ZSubParm = 0
  576.       CurrentCol = 1
  577.       CurrentRow = 3
  578.       IsBold = 99
  579.       END SUB
  580.  
  581. '*  DeleteCurrentLine()
  582. '*----------------------------------------------------------------------------
  583. '*  This routine deletes the current line on the screen and in the array
  584. '*  ZOutTxt$, and moves the next lower line up one  It then repaints the
  585. '*  affected portion of the screen (from the deleted line down)
  586. '*
  587. '*
  588.       SUB DeleteCurrentLine (Index%) STATIC
  589. 1600  FOR I = Index% TO 98
  590.          ZOutTxt$(I) = ZOutTxt$(I + 1)
  591.       NEXT I
  592.       ZOutTxt$(99) = BlankLine$
  593.       CALL UpdateScreen
  594.       END SUB
  595.  
  596. '*  DisplayMainMenu()
  597. '*----------------------------------------------------------------------------
  598. '*  This routine displays the main menu on the top line
  599. '*
  600. '*
  601.       SUB DisplayMainMenu STATIC
  602. 1700  CALL MoveCursor(1, 1)
  603.       CALL QuickTput(ZEmphasizeOff$, 0)
  604.       YY$ = " [H]elp  E)nd  R)eflow  J)ustify  I)ns/Ovw  P)aint  B)lock Delete   ESC Quits"
  605.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  606.       ZHiLiteOff = ZFalse
  607.       CALL ColorPrompt(YY$)
  608.       CALL PutScreen(YY$, 99, ZTrue)
  609.       IsBold = 99
  610.       END SUB
  611.  
  612. '*  DoneWithMsg()
  613. '*----------------------------------------------------------------------------
  614. '*  This routine is called to save or abort the message
  615. '*
  616. '*
  617.       SUB DoneWithMsg STATIC
  618. 1800  CALL SaveCursor(RowSave, ColSave)
  619.       CALL ClearMainMenu
  620.       CALL QuickTput(ZEmphasizeOff$, 0)
  621.       YY$ = "End Message: S)ave, A)bort, or [C]ontinue? "
  622.       ZHiLiteOff = ZFalse
  623.       CALL ColorPrompt(YY$)
  624.       CALL PutScreen(YY$, 99, ZTrue)
  625.       B$ = " "
  626.       WHILE INSTR("SAC" + CHR$(ESCKey) + CHR$(CarrRet), B$) = 0
  627.          CALL Getch(B$)
  628.          IF ZSubParm <> 0 THEN
  629.             EXIT SUB
  630.          END IF
  631.          CALL AllCaps(B$)
  632.       WEND
  633. 1810  SELECT CASE B$
  634.          CASE "S"        ' Save Message
  635.             CALL ClearScreen
  636.             '*
  637.             '* Remove trailing blank lines from the message
  638.             '*
  639.             EndOfMsg = ZMaxMsgLines
  640.             FOR I = ZMaxMsgLines TO 1 STEP -1
  641.                IF ZOutTxt$(I) <> BlankLine$ THEN
  642.                   EndOfMsg = I
  643.                   EXIT FOR
  644.                END IF
  645.             NEXT I
  646.             IF I = 0 THEN
  647.                EndOfMsg = 1
  648.             END IF
  649.             FOR I = 1 TO EndOfMsg
  650.                J = INSTR(ZOutTxt$(I), SoftSpace$)
  651.                WHILE J <> 0
  652.                   MID$(ZOutTxt$(I), J, 1) = " "
  653.                   J = INSTR(ZOutTxt$(I), SoftSpace$)
  654.                WEND
  655.             NEXT I
  656.             FOR I = EndOfMsg TO 1 STEP -1
  657.                CALL TrimTrail(ZOutTxt$, " ")
  658.                IF ZOutTxt$(I) <> BlankLine$ THEN
  659.                   EndOfMsg = I
  660.                   EXIT FOR
  661.                END IF
  662.             NEXT I
  663.             ZLinesInMsg = EndOfMsg
  664.             CALL QuickTput(ZEmphasizeOff$, 0)
  665.             ZSubParm = 1
  666.  
  667. 1820     CASE "A"
  668.             CALL ClearMainMenu
  669.             CALL QuickTput(ZEmphasizeOff$, 0)
  670.             YY$ = "Abort: Are You Sure (Y)es,[N]o)? "
  671.             ZHiLiteOff = ZFalse
  672.             CALL ColorPrompt(YY$)
  673.             CALL PutScreen(YY$, 99, ZTrue)
  674.             CALL Getch(B$)
  675.             IF ZSubParm <> 0 THEN
  676.                B$ = "Y"
  677.             END IF
  678.             CALL AllCaps(B$)
  679.             IF B$ = "Y" THEN
  680.                CALL ClearScreen
  681.                CALL QuickTput(ZEmphasizeOff$, 0)
  682.                ZSubParm = 2
  683.             END IF
  684.  
  685.          CASE ELSE
  686.             '*
  687.             '*
  688.       END SELECT
  689.       END SUB
  690.  
  691. '*  EraseToEOL()
  692. '*----------------------------------------------------------------------------
  693. '*  This routine clears from a position to to the end of that line
  694. '*
  695. '*
  696.       SUB EraseToEOL (LineNumber, ColNumber) STATIC
  697. 1900  CALL SaveCursor(RowSave, ColSave)
  698.       CALL MoveCursor(LineNumber, ColNumber)
  699.       CALL QuickTput("", 0)
  700.       CALL MoveCursor(RowSave, ColSave)
  701.       END SUB
  702.  
  703. '*  ExecuteMainMenuCommand()
  704. '*----------------------------------------------------------------------------
  705. '* This routine executes the passed main menu command
  706. '*
  707. '*
  708.       SUB ExecuteMainMenuCommand (CMD$) STATIC
  709. 2000  ZSubParm = 0
  710.       SELECT CASE CMD$
  711.          CASE "H"
  712.             CALL HelpMe
  713.          CASE "E"
  714.             CALL DoneWithMsg
  715.          CASE "P"
  716.             CALL ClearScreen
  717.             CALL UpdateScreen
  718.          CASE "I"
  719.             InsertMode = NOT InsertMode
  720.          CASE "R"
  721.             CALL ReformText(ZFalse)
  722.          CASE "J"
  723.             CALL ReformText(ZTrue)
  724.          CASE ELSE
  725.             '*
  726.             '*
  727.       END SELECT
  728.       IsBold = 99
  729.       IF ZSubParm = 0 THEN
  730.          CALL ClearMainMenu
  731.          CALL UpdateStatusLine(1)
  732.       END IF
  733.       END SUB
  734.  
  735. '*  FindWrap()
  736. '*----------------------------------------------------------------------------
  737. '*  This routine finds a place in the string yy$ that could be used as a
  738. '*  place to wrap the line WhereToWrap should be the last position that
  739. '*  remains in the line, ie
  740. '*    set   currentline$ = left$(yy$,wheretowrap)
  741. '*          nextline$    = mid$ (yy$,wheretowrap+1)
  742. '*
  743. '*
  744.       SUB FindWrap (YY$, WhereToWrap) STATIC
  745. 2100  I = LEN(YY$)
  746.       XX$ = " " + SoftSpace$
  747.       '*
  748.       '* Back over "False hits"
  749.       '*
  750.       ZZ$ = MID$(YY$, I, 1)
  751.       WHILE INSTR(XX$, ZZ$) <> 0 AND I <> 1
  752.          I = I - 1
  753.          ZZ$ = MID$(YY$, I, 1)
  754.       WEND
  755.       WHILE INSTR(XX$, ZZ$) = 0 AND I <> 1
  756.          I = I - 1
  757.          ZZ$ = MID$(YY$, I, 1)
  758.       WEND
  759.       WhereToWrap = I
  760.       END SUB
  761.  
  762. '*  Getch()
  763. '*----------------------------------------------------------------------------
  764. '*  This routine reads a character from the user into YY$
  765. '*
  766. '*
  767.       SUB Getch (YY$) STATIC
  768. 2200  ZAutoLogoff! = TIMER + ZWaitBeforeDisconnect
  769.       CALL Carrier
  770.       YY$ = ""
  771.       WHILE ZSubParm <> -1 AND ZSubParm <> -2 AND YY$ = ""
  772.          ZSubParm = 0
  773.          IF LEN(ZCommportStack$) > 0 THEN
  774.             YY$ = LEFT$(ZCommportStack$, 1)
  775.             ZCommportStack$ = MID$(ZCommportStack$, 2)
  776.          ELSE
  777.             IF ZLocalUser THEN
  778.                YY$ = INKEY$
  779.                IF LEN(YY$) = 2 THEN
  780.                   KeyPressed = ASC(RIGHT$(YY$, 1))
  781.                   YY$ = ""
  782.                   SELECT CASE KeyPressed
  783.                      CASE 82                  ' Insert
  784.                         YY$ = CHR$(ToggleINSKey)
  785.                      CASE 83                  ' Delete
  786.                         YY$ = CHR$(CharDeleteKey)
  787.                      CASE 71                  ' Home
  788.                         YY$ = CHR$(HomeKey)
  789.                      CASE 73                  ' PgUp
  790.                         YY$ = CHR$(PageUpKey)
  791.                      CASE 72                  ' Up Arrow
  792.                         YY$ = CHR$(LineUpKey)
  793.                      CASE 80                  ' Down Arrow
  794.                         YY$ = CHR$(LineDownKey)
  795.                      CASE 81                  ' PgDn
  796.                         YY$ = CHR$(PageDownKey)
  797.                      CASE 75                  ' Left Arrow
  798.                         YY$ = CHR$(ColLeftKey)
  799.                      CASE 77                  ' Right Arrow
  800.                         YY$ = CHR$(ColRightKey)
  801.                      CASE 115                 ' Ctrl-Left Arrow
  802.                         YY$ = CHR$(WordLeftKey)
  803.                      CASE 116                 ' Ctrl-Right Arrow
  804.                         YY$ = CHR$(WordRightKey)
  805.                      CASE 79                  ' End
  806.                         YY$ = CHR$(EndKey)
  807.                      CASE ELSE
  808.                         '*
  809.                         '*
  810.                   END SELECT
  811.                END IF
  812.             ELSE
  813.                CALL FindFKey
  814.                IF ZSubParm >= 0 THEN
  815.                   YY$ = ZKeyPressed$
  816.                   IF YY$ = "" THEN
  817.                      CALL EofComm(Char%)
  818.                      IF Char% = -1 THEN
  819.                         CALL CheckTime(ZAutoLogoff!, Remain!, 1)
  820.                         IF Remain! < 0 THEN
  821.                            CALL UpdtCalr("Sleep disconnect", 1)
  822.                            ZSubParm = -2
  823.                            ZNo = ZTrue
  824.                            ZSleepDisconnect = ZTrue
  825.                         END IF
  826.                      ELSE
  827.                         CALL Carrier
  828.                         IF ZSubParm <> -1 THEN
  829.                            ZSubParm = 0
  830.                            CALL GetCom(YY$)
  831.                         END IF
  832.                      END IF
  833.                   END IF
  834.                END IF
  835.             END IF
  836.          END IF
  837.       WEND
  838.       END SUB
  839.  
  840. '*  HelpMe()
  841. '*----------------------------------------------------------------------------
  842. '*  This routine provides on-line help for the user
  843. '*
  844. '*
  845.       SUB HelpMe STATIC
  846. 2300  CALL SaveCursor(RowSave, ColSave)
  847.       CALL ClearScreen
  848.       CALL QuickTput(ZEmphasizeOff$, 0)
  849.       CALL BufFile(ZHelpPath$ + "ANSIED" + ZHelpExtension$, X)
  850.       OldColour = 0
  851.       IsBold = 99
  852.       CALL ClearScreen
  853.       FOR I = 3 TO 24
  854.          ZWorkAra$(I) = BlankLine$
  855.       NEXT I
  856.       CALL UpdateScreen
  857.       CALL MoveCursor(ColSave, RowSave)
  858.       END SUB
  859.  
  860. '*  LastParaLine()
  861. '*----------------------------------------------------------------------------
  862. '*  This routine returns ZTrue if ZOutTxt$(I) is the last line
  863. '*  in a paragraph
  864. '*
  865. '*
  866.       SUB LastParaLine (I, LastLine, Result) STATIC
  867. 2400  Result = ZFalse
  868.       IF I = LastLine OR I >= ZMaxMsgLines THEN
  869.          Result = ZTrue
  870.       ELSE
  871.          YY$ = ZOutTxt$(I)
  872.          J = INSTR(YY$, ">")
  873.          IF J = 0 THEN
  874.             J = 6
  875.          END IF
  876.          IF J < 5 THEN
  877.             Result = ZTrue
  878.          ELSEIF YY$ = BlankLine$ THEN
  879.             Result = ZTrue
  880.          ELSE
  881.             IF ZOutTxt$(I + 1) = BlankLine$ THEN
  882.                Result = ZTrue
  883.             ELSEIF LEFT$(ZOutTxt$(I + 1), 1) = " " THEN
  884.                Result = ZTrue
  885.             ELSE
  886.                K = INSTR(ZOutTxt$(I + 1), ">")
  887.                IF K <> 0 AND K < 5 THEN
  888.                   Result = ZTrue
  889.                END IF
  890.             END IF
  891.          END IF
  892.       END IF
  893.       END SUB
  894.  
  895. '*  MoveCursor()
  896. '*----------------------------------------------------------------------------
  897. '*  This routine moves the cursor to the position spec'd by newcol and
  898. '*  newrow and tries to do it with the minimum number of Ansi characters
  899. '*
  900. '*
  901.       SUB MoveCursor (NewRow, NewCol) STATIC
  902. 2500  IF CurrentRow = NewRow AND CurrentCol = NewCol THEN
  903.          EXIT SUB
  904.       ELSEIF NewCol = 0 AND NewRow = 0 THEN
  905.          EXIT SUB
  906.       ELSEIF NewCol = 1 AND NewRow = 1 THEN
  907.          YY$ = "f"
  908.       ELSEIF NewCol <> CurrentCol AND NewRow <> CurrentRow THEN
  909.          YY$ = "" + MID$(STR$(NewRow), 2) + ";" + MID$(STR$(NewCol), 2) + "f"
  910.       ELSE
  911.          IF CurrentCol = NewCol THEN           ' Just the row has changed
  912.             I = CurrentRow - NewRow
  913.             C$ = "A"   ' A=Up, B=Down
  914.          ELSE                                   ' Just the column changed
  915.             I = NewCol - CurrentCol
  916.             C$ = "C"   ' C=Left, D=Right
  917.          END IF
  918.          '*
  919.          '* Adjust the direction of the cursor
  920.          '*
  921.          IF I < 0 THEN
  922.             I = -I
  923.             C$ = CHR$(ASC(C$) + 1)
  924.          END IF
  925.          YY$ = ""
  926.          IF I > 1 THEN
  927.             YY$ = YY$ + MID$(STR$(I), 2)
  928.          END IF
  929.          YY$ = YY$ + C$
  930.       END IF
  931.       CALL QuickTput(YY$, 0)
  932.       ZSubParm = 0
  933.       CurrentRow = NewRow
  934.       CurrentCol = NewCol
  935.       END SUB
  936.  
  937. '*  NormalChar()
  938. '*----------------------------------------------------------------------------
  939. '*  This routine handles 'normal' characters entered into the message
  940. '*
  941. '*
  942.       SUB NormalChar (YY$) STATIC
  943.  
  944. 2600  CALL SaveCursor(RowSave, ColSave)
  945.       Index = CurrentRow + TopLine - 3
  946.       CurrentLineBlank = (ZOutTxt$(Index) = BlankLine$)
  947.       LML = LEN(ZOutTxt$(Index))
  948.  
  949.       IF CurrentCol > 79 THEN
  950.          EXIT SUB
  951.       END IF
  952.  
  953.       AtEndOfLine = ZFalse
  954.  
  955.       IF CurrentCol > LML THEN
  956.          ZOutTxt$(Index) = ZOutTxt$(Index) + SPACE$(CurrentCol - LML)
  957.          ZWorkAra$(CurrentRow) = ZWorkAra$(CurrentRow) + SPACE$(CurrentCol - LML)
  958.          LML = LEN(ZOutTxt$(Index))
  959.          AtEndOfLine = ZTrue
  960.       END IF
  961.  
  962. 2610  IF (CurrentCol <= ZRightMargin AND AtEndOfLine) OR (CurrentCol <= ZRightMargin AND NOT InsertMode) THEN
  963.          '*
  964.          '* Single character changed
  965.          '*
  966.          MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  967.          MID$(ZWorkAra$(CurrentRow), CurrentCol, 1) = YY$
  968.          CALL PutScreen(YY$, YellowFore, ZTrue)
  969.  
  970. 2620  ELSEIF (NOT AtEndOfLine AND InsertMode AND CurrentCol <= ZRightMargin AND LML <= ZRightMargin) THEN
  971.          '*
  972.          '* Have to rewrite the screen from the current pos forward
  973.          '*
  974.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  975.  
  976.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  977.  
  978.          CALL EraseToEOL(CurrentRow, CurrentCol)
  979.          ZZ$ = MID$(ZWorkAra$(CurrentRow), CurrentCol)
  980.          CALL PutScreen(ZZ$, YellowFore, ZTrue)
  981.          CALL MoveCursor(RowSave, ColSave + 1)
  982.  
  983. 2630  ELSE
  984.          '*
  985.          '* Wrap the end of the line
  986.          '*
  987.          IF NOT AtEndOfLine THEN
  988.             ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), CurrentCol - 1) + YY$ + MID$(ZOutTxt$(Index), CurrentCol)
  989.             LML = LML + 1
  990.          ELSE
  991.             MID$(ZOutTxt$(Index), CurrentCol, 1) = YY$
  992.          END IF
  993.  
  994.          CALL FindWrap(ZOutTxt$(Index), I)
  995.          IF I = 0 OR I = 1 THEN
  996.             I = ZRightMargin
  997.          END IF
  998.  
  999.          ZZ$ = MID$(ZOutTxt$(Index), (I + 1))
  1000.          CALL RightTrim(ZZ$)
  1001.          ZOutTxt$(Index) = LEFT$(ZOutTxt$(Index), I)
  1002.          ' add to the beginning of a new line
  1003.          IF Index <= 98 THEN
  1004.             Index = Index + 1
  1005.          END IF
  1006.          FOR J = 98 TO Index STEP -1
  1007.             ZOutTxt$(J + 1) = ZOutTxt$(J)
  1008.          NEXT J
  1009.          ZOutTxt$(Index) = ZZ$
  1010.  
  1011.          CALL EraseToEOL(CurrentRow, I + 1)        ' do the "easy" line
  1012.          ZWorkAra$(CurrentRow) = ZOutTxt$(Index)
  1013.  
  1014.          CALL UpdateScreen
  1015.          IF (ColSave > I) THEN
  1016.             NewCol = ColSave - I + 1
  1017.             IF RowSave <> 24 THEN
  1018.                CALL MoveCursor(RowSave + 1, NewCol)
  1019.             ELSE
  1020.                CALL MoveCursor(RowSave, NewCol)
  1021.                CALL Ungetch(LineDownKey)
  1022.             END IF
  1023.          ELSE
  1024.             CALL MoveCursor(RowSave, ColSave + 1)
  1025.          END IF
  1026.       END IF
  1027.  
  1028.       END SUB
  1029.  
  1030. '*  PutScreen()
  1031. '*----------------------------------------------------------------------------
  1032. '* This routine writes YY$ to the user in the color and
  1033. '* intensity specified
  1034. '*
  1035. '*
  1036.       SUB PutScreen (YY$, Colour, Bold) STATIC
  1037. 2800  ZZ$ = ""
  1038.       IF Colour <> 99 THEN
  1039.          IF (Colour <> OldColour) OR (Bold <> IsBold) THEN
  1040.             ZZ$ = ""
  1041.             IF Bold <> IsBold THEN
  1042.                IF Bold THEN
  1043.                   ZZ$ = ZZ$ + "1;"
  1044.                   IsBold = ZTrue
  1045.                ELSE
  1046.                   ZZ$ = ZZ$ + "0;"
  1047.                   IsBold = ZFalse
  1048.                END IF
  1049.             END IF
  1050.             ZZ$ = ZZ$ + MID$(STR$(Colour), 2)
  1051.             ZZ$ = ZZ$ + "m"
  1052.          END IF
  1053.       END IF
  1054.       ZOutTxt$ = ZZ$ + YY$
  1055.       IF ZLocalUser THEN
  1056.          CALL QuickTput(ZOutTxt$, 0)
  1057.       ELSE
  1058.          ZSubParm = 4
  1059.          CALL Tput
  1060.          ZSubParm = 0
  1061.       END IF
  1062.       IF INSTR(YY$, "") = 0 THEN
  1063.          CurrentCol = CurrentCol + LEN(YY$)
  1064.          IF CurrentCol > 80 THEN
  1065.             CurrentCol = 0
  1066.             CurrentRow = 0
  1067.          END IF
  1068.       ELSE
  1069.          CurrentRow = 0
  1070.          CurrentCol = 0
  1071.       END IF
  1072.       OldColour = Colour
  1073.       Colour = 99
  1074.       END SUB
  1075.  
  1076. '*  ReformText()
  1077. '*----------------------------------------------------------------------------
  1078. '*  This routine reflows the text to the current margins.  Optionally,
  1079. '*  it right justifies all lines by adding "soft spaces"
  1080. '*
  1081. '*
  1082.       SUB ReformText (Justify%) STATIC
  1083.  
  1084. 2900  DIM SpacePlace(80)
  1085.  
  1086.       CALL ClearMainMenu
  1087.       CALL PutScreen("Reformatting... Please Wait.", WhiteFore, ZTrue)
  1088.  
  1089.       LastLine = 1
  1090.       FOR I = ZMaxMsgLines TO 1 STEP -1
  1091.          IF ZOutTxt$(I) <> BlankLine$ THEN
  1092.             LastLine = I
  1093.             EXIT FOR
  1094.          END IF
  1095.       NEXT
  1096.  
  1097.       I = MsgLockLines + 1   ' Read index
  1098.       J = MsgLockLines + 1   ' Write index
  1099.  
  1100.       '*
  1101.       '* Reflow the text to the maximum on a line
  1102.       '*
  1103.       DO WHILE I <= LastLine
  1104.          ZOutTxt$ = ""
  1105.          DO WHILE 1
  1106.             YY$ = ZOutTxt$(I)
  1107.             CALL UnString(YY$, SoftSpace$)
  1108.             IF ZOutTxt$ <> "" AND RIGHT$(ZOutTxt$, 1) <> " " THEN
  1109.                ZOutTxt$ = ZOutTxt$ + " "
  1110.             END IF
  1111.             ZOutTxt$ = ZOutTxt$ + YY$
  1112.             CALL LastParaLine(I, LastLine, Z)
  1113.             IF LEN(ZOutTxt$) > ZRightMargin OR Z THEN
  1114.                IF LEN(ZOutTxt$) > ZRightMargin THEN
  1115.                   CALL FindWrap(LEFT$(ZOutTxt$, ZRightMargin + 1), K)
  1116.                   IF K = 0 OR K = 1 THEN K = ZRightMargin
  1117.                   ZOutTxt$(J) = LEFT$(ZOutTxt$, K)
  1118.                   IF Z THEN
  1119.                      ' Go to the next paragraph
  1120.                      ZOutTxt$(J + 1) = MID$(ZOutTxt$, K + 1)
  1121.                      J = J + 2
  1122.                      I = I + 1
  1123.                      EXIT DO
  1124.                   ELSE
  1125.                      ZOutTxt$(I) = MID$(ZOutTxt$, K + 1)
  1126.                      J = J + 1
  1127.                      EXIT DO
  1128.                   END IF
  1129.                ELSE          ' Z is ZTrue
  1130.                   ZOutTxt$(J) = ZOutTxt$
  1131.                   J = J + 1
  1132.                   I = I + 1
  1133.                   EXIT DO
  1134.                END IF
  1135.             ELSE
  1136.                I = I + 1
  1137.             END IF
  1138.          LOOP
  1139.       LOOP
  1140.  
  1141.       FOR I = J TO 99
  1142.          ZOutTxt$(I) = BlankLine$
  1143.       NEXT
  1144.  
  1145.       LastLine = J - 1
  1146.  
  1147.       '*
  1148.       '* Space out the text on each line
  1149.       '*
  1150.       IF Justify% THEN
  1151.          FOR I = MsgLockLines + 1 TO LastLine
  1152.             CALL LastParaLine(I, LastLine, Z)
  1153.             IF Z THEN
  1154.             ELSE
  1155.                ZOutTxt$ = ZOutTxt$(I)
  1156.                CALL TrimTrail(ZOutTxt$, " ")
  1157.                '*
  1158.                '* Skip leading spaces on the line
  1159.                '*
  1160.                J = -1
  1161.                FOR K = 1 TO LEN(ZOutTxt$)
  1162.                   IF MID$(ZOutTxt$, K, 1) <> " " THEN
  1163.                      J = K
  1164.                      EXIT FOR
  1165.                   END IF
  1166.                NEXT
  1167.                IF J <> -1 THEN
  1168.                   '*
  1169.                   '* Find out all of the possible places to put spaces
  1170.                   '*
  1171.                   L = 0
  1172.                   M = INSTR(J, ZOutTxt$, " ")
  1173.                   WHILE M <> 0
  1174.                      L = L + 1
  1175.                      SpacePlace(L) = M
  1176.                      M = INSTR(M + 1, ZOutTxt$, " ")
  1177.                   WEND
  1178.                   IF L <> 0 THEN
  1179.                      '*
  1180.                      '* Space out the line.  First add a space to the
  1181.                      '* start of the line, then add to the end.
  1182.                      '*
  1183.                      SpacesToAdd = ZRightMargin - LEN(ZOutTxt$)
  1184.                      M = 1
  1185.                      N = L
  1186.                      DoM = ZTrue
  1187.                      WHILE SpacesToAdd <> 0
  1188.                         IF DoM THEN
  1189.                            Place = SpacePlace(M)
  1190.                            M = M + 1
  1191.                         ELSE
  1192.                            Place = SpacePlace(N)
  1193.                            N = N - 1
  1194.                         END IF
  1195.                         DoM = NOT DoM
  1196.                         ZOutTxt$(I) = LEFT$(ZOutTxt$(I), Place) + SoftSpace$ + MID$(ZOutTxt$(I), Place + 1)
  1197.                         SpacesToAdd = SpacesToAdd - 1
  1198.                         FOR P = 1 TO L
  1199.                            IF SpacePlace(P) > Place THEN
  1200.                               SpacePlace(P) = SpacePlace(P) + 1
  1201.                            END IF
  1202.                         NEXT
  1203.                         IF M = N THEN
  1204.                            M = 1
  1205.                            N = L
  1206.                         END IF
  1207.                      WEND
  1208.                   END IF
  1209.                END IF
  1210.             END IF
  1211.          NEXT
  1212.       END IF
  1213.  
  1214.       CALL UpdateScreen
  1215.  
  1216.       END SUB
  1217.  
  1218. '*  RightTrim()
  1219. '*----------------------------------------------------------------------------
  1220. '*   Removes soft spaces from a string
  1221. '*
  1222. '*
  1223.       SUB RightTrim (YY$) STATIC
  1224. 3000  FOR I = LEN(YY$) TO 1 STEP -1
  1225.          IF MID$(YY$, I, 1) <> SoftSpace$ THEN
  1226.             YY$ = LEFT$(YY$, I)
  1227.             EXIT SUB
  1228.          END IF
  1229.       NEXT I
  1230.       YY$ = ""
  1231.       END SUB
  1232.  
  1233. '*  SaveCursor()
  1234. '*----------------------------------------------------------------------------
  1235. '*  This routine saves the current cursor position
  1236. '*
  1237. '*
  1238.       SUB SaveCursor (Row%, Col%) STATIC
  1239.       Row% = CurrentRow
  1240.       Col% = CurrentCol
  1241.       END SUB
  1242.  
  1243. '*  UnGetch()
  1244. '*----------------------------------------------------------------------------
  1245. '*   Puts a key in the beginning of the keyboard buffer
  1246. '*
  1247. '*
  1248.       SUB Ungetch (X) STATIC
  1249.       ZCommportStack$ = CHR$(X) + ZCommportStack$
  1250.       END SUB
  1251.  
  1252. '*  UnString()
  1253. '*----------------------------------------------------------------------------
  1254. '*  Removes one string from another
  1255. '*
  1256. '*
  1257.       SUB UnString (WasL$, BadString$) STATIC
  1258.       WasI = INSTR(WasL$, BadString$)
  1259.       WHILE WasI <> 0
  1260.          WasL$ = LEFT$(WasL$, WasI - 1) + MID$(WasL$, WasI + LEN(BadString$))
  1261.          WasI = INSTR(WasL$, BadString$)
  1262.       WEND
  1263.       END SUB
  1264.  
  1265. '*  UpdateScreen()
  1266. '*----------------------------------------------------------------------------
  1267. '*  This is one of the most important routines  It compares the arrays
  1268. '*  ZOutTxt$ and ZWorkAra$ and only sends the user the DIFFERENCE between the
  1269. '*  two within the viewing area  In this way all processing can be done on
  1270. '*  ZOutTxt$ and then the screen is updated to reflect the changes. After the
  1271. '*  users screen is updated, ZWorkAra$ is changed to reflect what should be
  1272. '*  on the users' screen The cursor is restored to its original position
  1273. '*
  1274. '*
  1275.       SUB UpdateScreen STATIC
  1276. 3100  CALL SaveCursor(RowSave, ColSave)
  1277.       FOR I = 3 TO 24
  1278.          Index = I + TopLine - 3
  1279.          ScreenLine$ = ZWorkAra$(I)
  1280.          MessageLine$ = ZOutTxt$(Index)
  1281.          LML = LEN(MessageLine$)
  1282.          IF Index = ZMaxMsgLines + 1 THEN
  1283.             CALL EraseToEOL(I, 1)
  1284.             CALL MoveCursor(I, 1)
  1285.             CALL PutScreen("[* End of Message *]", CyanFore, ZFalse)
  1286.             ZWorkAra$(I) = CHR$(EndKey)
  1287.          ELSEIF Index > ZMaxMsgLines + 1 THEN
  1288.             IF ScreenLine$ <> BlankLine$ THEN
  1289.                CALL EraseToEOL(I, 1)
  1290.                ZWorkAra$(I) = BlankLine$
  1291.             END IF
  1292.          ELSEIF MessageLine$ = ScreenLine$ THEN
  1293.             '*
  1294.             '* Screen = What's in message buffer
  1295.             '*
  1296.          ELSEIF MessageLine$ = BlankLine$ OR MessageLine$ = SPACE$(LML) THEN
  1297.             CALL EraseToEOL(I, 1)
  1298.             ZWorkAra$(I) = MessageLine$
  1299.          ELSE
  1300.             CALL MoveCursor(I, 1)
  1301.             YY$ = MessageLine$
  1302.             CALL PutScreen(YY$, YellowFore, ZTrue)
  1303.             CALL EraseToEOL(CurrentRow, CurrentCol)
  1304.             ZWorkAra$(I) = ZOutTxt$(Index)
  1305.          END IF
  1306.       NEXT I
  1307.       CALL MoveCursor(RowSave, ColSave)
  1308.       END SUB
  1309.  
  1310. '*  UpdateStatusLine()
  1311. '*-----------------------------------------------------------------------------
  1312. '*  Rewrites the status line on screen line(s) 1 and 2
  1313. '*
  1314. '*    Input:  How% = 1   - Rewrite both lines
  1315. '*            How% = 2   - Just rewrite top line
  1316. '*
  1317.       SUB UpdateStatusLine (How%) STATIC
  1318. 3200  YY$ = "ANSIED " + Version$ + " by Tom Collins                       * Press ESC Twice for Menu *"
  1319.       YY$ = YY$ + SPACE$(79 - LEN(YY$))
  1320.       CALL MoveCursor(1, 1)
  1321.       CALL PutScreen(YY$, BlueFore, ZTrue)
  1322. 3210  IF How% = 1 THEN
  1323.          YY$ = CHR$(205) + " To: " + MsgTo$ + " " + STRING$(3, CHR$(205)) + " Subject: " + MsgSubj$ + " " + STRING$(3, CHR$(205))
  1324.          InsOvwPosition = LEN(YY$)
  1325.          IF InsertMode THEN
  1326.             YY$ = YY$ + " Insert " + STRING$(3, CHR$(205))
  1327.          ELSE
  1328.             YY$ = YY$ + " Overwrite "
  1329.          END IF
  1330.          YY$ = YY$ + STRING$(79 - LEN(YY$), CHR$(205))
  1331.          I = 1
  1332.          CALL MoveCursor(2, I)
  1333.          CALL PutScreen(YY$, WhiteFore, ZFalse)
  1334.       END IF
  1335.       END SUB
  1336.  
  1337.